/*
* @Author: z.p
* @Project: Zdotp
* @Date: 2024年12月30日
* @Description: 基于actor模型的网关actor, 负责进行客户端消息转发
*/

using Google.Protobuf;
using Zdotp.Net.Kcp.App;
using Zdotp.Pb;

namespace Zdotp.Actor.Kcp;

// [Component(typeof(Test1Component))]
// [Component(typeof(Test2Component))]
public sealed class ActorKcp : ActorBase
{
    private readonly ServerApp _app;
    private readonly int _port;

    public ActorKcp(string ip, int port)
    {
        _app = new ServerApp();
        _app.OnConnected += session =>
        {
            ReceiveMessage(MyActorSystem.CreateMail<ConnectMessage>(), ActorId, session.SessionId);
        };
        _app.OnDisconnected += session =>
        {
            ReceiveMessage(MyActorSystem.CreateMail<DisConnectMessage>(), ActorId, session.SessionId);
        };
        _app.OnReceive += (session, packet) =>
        {
            var protocolId = BitConverter.ToUInt32(packet, 4);
            if (protocolId == 0)
            {
                ServerCloseClient(session.SessionId);
                return;
            }
            var data = packet.Skip(8).ToArray();
            ReceiveMessage(MyActorSystem.CreateMail<ReadMessage>(message =>
            {
                message.ProtocolId = protocolId;
                message.Data = data;
            }), ActorId, session.SessionId);
        };
        _app.Start(ip, port);
        _port = port;
    }

    public void SendMsgToAllClient(byte[] packet) => _app.SendMsgToAllClient(packet);
    
    public void SendMsgToClient(uint sessionId, byte[] msg) => _app.SendMsgToClient(sessionId, msg);

    public void SendMsgToClient<T>(uint sessionId, T data) where T : IMessage<T>
    {
        var type = typeof(T);
        var protocolId = ActorSystem.NetGetProtocolId(type);
        var bytes = data.Serialize();
        
        var protocolIdBytes = BitConverter.GetBytes(protocolId);
        
        var result = new byte[4 + bytes.Length];
        Array.Copy(protocolIdBytes, 0, result, 0, 4);
        Array.Copy(bytes, 0, result, 4, bytes.Length);

        _app.SendMsgToClient(sessionId, result);
    }

    private void ServerCloseClient(uint sessionId) => _app.ServerCloseClient(sessionId);
    public bool HasSession(uint sessionId) => _app.HasSession(sessionId);
    protected override void OnAwake()
    {
        
    }

    protected override void OnStart()
    {
        Logger.Info($"Kcp port : {_port} ...");
    }

    protected override void OnUpdate(float deltaTime)
    {
        
    }

    protected override void OnDestroy()
    {
        
    }
}